/******************************************************************************
 *  _____     _____
 *  \  __\    \  __\
 *   \ \_\\    \ \_\\
 *    \  __\SS  \  __\roject
 *     \_\       \_\
 *
 * Mateusz Maciąg, Rafał Urbański
 * Komputerowe Systemy Sterowania
 *****************************************************************************/

#include "ControllerBase.h"

#include <sstream>
#include "Utils.h"


// Przestrzeń nazw
namespace RafMat
{
namespace SimEngine
{

using namespace std;
using namespace SimInterface;

const string ControllerBase::CONF_TYPE("type");

ControllerBase::ControllerBase(SimInterface::ISimulator &isim, std::string type)
    : SISOModel(isim, "Controller"),
      m_waveformContainer(WaveformContainerSPtr(new WaveformContainer(isim))),
	  m_currentSetPoint(0), m_currentError(0), m_currentOutput(0),
      m_type(type)
{
}

ControllerBase::ControllerBase(SimInterface::ISimulator &isim, std::string type,
                               WaveformContainerSPtr wfrmContainer)
    : SISOModel(isim, "Controller"),
      m_waveformContainer(wfrmContainer),
	  m_currentSetPoint(0), m_currentError(0), m_currentOutput(0),
      m_type(type)
{
}

ControllerBase::ControllerBase(SimInterface::ISimulator &isim, std::string type, std::string name)
    : SISOModel(isim, name),
      m_waveformContainer(WaveformContainerSPtr(new WaveformContainer(isim))),
	  m_currentSetPoint(0), m_currentError(0), m_currentOutput(0),
      m_type(type)
{
}

ControllerBase::ControllerBase(SimInterface::ISimulator &isim, std::string type,
                               std::string name,
                               WaveformContainerSPtr wfrmContainer)
    : SISOModel(isim, name),
      m_waveformContainer(WaveformContainerSPtr(wfrmContainer)),
	  m_currentSetPoint(0), m_currentError(0), m_currentOutput(0),
      m_type(type)
{
}

double ControllerBase::simulateStep(double sample)
{
    m_currentProcessVariable = sample;
    // Oblicz aktualną wartość zadaną na podstawie zawartości kontenera z sygnałami.
    m_currentSetPoint = m_waveformContainer->currentValue();

    // Oblicz aktualny uchyb.
    m_currentError = m_currentSetPoint - sample;

    // Wywołaj polimorficzną metodę zależną od konkretnego regulatora.
    return m_currentOutput = simulateControllerStep(m_currentSetPoint, sample);
}

SimFile::ConfigWriter& ControllerBase::dumpParameters(SimFile::ConfigWriter& o) const
{
    o.pushBlock(SimFile::ConfigWriter::BlockController, getName());
    o.pushParam(CONF_TYPE, m_type);
    this->dumpSpecificPar(o);
    o.closeBlock();
    return o;
}

//
// Konfiguracja
//

std::string ControllerBase::getParameter(const std::string& param) const throw(std::logic_error)
{
    typedef ostream_iterator<double> oit;

    string tparam = Utils::trimWhiteSpaces(param);

    string tmpOut;
    ostringstream ostr(tmpOut);

    if(tparam == CONF_TYPE)
    {
        ostr << m_type;
    }
    else
        throw iconf_error::unrecognizedParam(*this, tparam);

    return ostr.str();
}

SimFile::ConfigWriter& ControllerBase::dumpSpecificPar(SimFile::ConfigWriter& o) const
{
    // Nie rób nic
    return o;
}

}   // SimEngine namespace
}   // RafMat namespace
